#include"common.hpp"
#include"Log.hpp"
#include"Socket.hpp"
#include <poll.h>
#include<sys/select.h>


class PollServer{
    const static int defaultfd = -1;
    // const static int size = 1024;
#define SIZE 1024
public:
    PollServer(int port)
    :_server(std::make_unique<TcpSocket>())
    ,_isrunning(false)
    {
        _server->BuideTcpSocket(port);
        for(int i = 0;i < SIZE;i++){
            pfds[i].fd = defaultfd;
        }
        pfds[0].fd = _server->Getfd();
        pfds[0].events = POLLIN;
        pfds[0].revents = 0;

    }   

    void Accept(int pos){
        Inetaddr iaddr;
        int tmpfd = _server->Accept(&iaddr);
        if(tmpfd < 0){
            LOG(level::WARING)<<"accept false";
            return;
        }
        for(int i = 0; i < SIZE;i++){
            if(pfds[i].fd == defaultfd){
                pfds[i].fd = tmpfd;
                pfds[i].events = POLLIN;
                pfds[i].revents = 0;    
                break;
            }
        }

    }

    void Recv(int pos){
        char buff[1024];
        int size = recv(pfds[pos].fd,buff,sizeof(buff)-1,0);
        if(size > 0){
            buff[size] = 0;
            std::cout<<buff<<std::endl;
        }
        else if(size == 0){
            pfds[pos].fd = defaultfd;
            pfds[pos].events = 0;
            pfds[pos].revents = 0;
            LOG(level::DEBUG)<<"exit...";
        }
        else{
            pfds[pos].fd = defaultfd;
            pfds[pos].events = 0;
            pfds[pos].revents = 0;
            LOG(level::ERROR)<<"recv ERR";
        }
    }

    void Dispatch(){
        for(int i = 0;i < SIZE;i++){
            if(pfds[i].fd == defaultfd)
                continue;
            if(pfds[i].revents == POLLIN){
                if(pfds[i].fd == _server->Getfd())
                    Accept(i);
                Recv(i);
            }
            if(pfds[i].revents == POLLOUT){}
        }
    }

    void start(){
        _isrunning = true;
        int timeout = -1;
        while(_isrunning){
            int ret = poll(pfds,SIZE,timeout);
            switch (ret)
            {
            case -1:
                LOG(level::WARING)<<"select fail";
                break;
            case 0:
                LOG(level::DEBUG)<<"timeout..";
                break;
            default:
                Dispatch();
                break;
            }

        }
        _isrunning = false;
    }

    void Stop()
    {
        _isrunning = false;
    }

    ~PollServer(){}

private:
    std::unique_ptr<Socket> _server;
    bool _isrunning;

    struct pollfd pfds[SIZE];
    
};